package com.snail.wms.base.business.category.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.snail.common.core.constant.CommonConstants;
import com.snail.common.core.enums.BizStatus;
import com.snail.common.core.exception.ServiceException;
import com.snail.common.core.utils.PageUtils;
import com.snail.common.core.utils.StringUtils;
import com.snail.common.core.web.page.PageResult;
import com.snail.common.sequence.utils.SequenceUtils;
import com.snail.wms.base.business.category.domain.BaseCategory;
import com.snail.wms.base.business.category.dto.BaseCategoryDto;
import com.snail.wms.base.business.category.mapper.BaseCategoryMapper;
import com.snail.wms.base.business.category.query.BaseCategoryQuery;
import com.snail.wms.base.business.category.service.IBaseCategoryService;
import com.snail.wms.base.constants.BaseConstants;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 产品分类Service业务层处理
 * @Author: snail
 * @CreateDate: 2024-04-24
 * @Version: V1.0
 */
@Service
public class BaseCategoryServiceImpl extends ServiceImpl<BaseCategoryMapper, BaseCategory> implements IBaseCategoryService {

    @Autowired
    private SequenceUtils sequenceUtils;

    @Override
    public PageResult<BaseCategory> selectBaseCategoryPage(BaseCategoryQuery query) {
        Page<BaseCategory> page = PageUtils.buildPage(query);
        LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
        //分类编码
        queryWrapper.like(StringUtils.isNotEmpty(query.getCategoryCode()), BaseCategory::getCategoryCode, query.getCategoryCode());
        //分类名称
        queryWrapper.like(StringUtils.isNotEmpty(query.getCategoryName()), BaseCategory::getCategoryName, query.getCategoryName());
        //父分类id
        queryWrapper.eq(StringUtils.isNotEmpty(query.getParentCategoryId()), BaseCategory::getParentId, query.getParentCategoryId());
        //状态：1.启用，0.禁用
        queryWrapper.eq(StringUtils.isNotEmpty(query.getCategoryStatus()), BaseCategory::getCategoryStatus, query.getCategoryStatus());
        //分类全路径
        queryWrapper.like(StringUtils.isNotEmpty(query.getCategoryFullName()), BaseCategory::getCategoryFullName, query.getCategoryFullName());
        queryWrapper.ge(StringUtils.isNotEmpty(query.getBeginTime()), BaseCategory::getCreateTime, query.getBeginTime());
        queryWrapper.le(StringUtils.isNotEmpty(query.getEndTime()), BaseCategory::getCreateTime, query.getEndTime());
        queryWrapper.orderByAsc(BaseCategory::getCreateTime);
        page = baseMapper.selectPage(page, queryWrapper);
        return PageUtils.pageResult(page);
    }

    @Override
    public BaseCategory getBaseCategoryById(String categoryId) {
        return getById(categoryId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String insertBaseCategory(BaseCategory baseCategory) {
        //设置分类信息
        setCategoryInfo(baseCategory);
        //保存分类
        save(baseCategory);
        return baseCategory.getCategoryId();
    }

    /**
     * 设置分类其他信息
     *
     * @param baseCategory 分类信息
     */
    private void setCategoryInfo(BaseCategory baseCategory) {
        //编码规则
        String categoryCodeRule = BaseConstants.CATEGORY_CODE_RULE + baseCategory.getCategoryLevel();
        //分类编码
        String code = sequenceUtils.getSequence(categoryCodeRule);
        //全路径
        if (BaseConstants.CATEGORY_ROOT_ID.equals(baseCategory.getParentId())) {
            baseCategory.setCategoryCode(code);
            baseCategory.setCategoryFullName(baseCategory.getCategoryName());
        } else {
            BaseCategory parent = getById(baseCategory.getParentId());
            if (parent == null) {
                throw new ServiceException("父分类信息不存在!");
            }
            baseCategory.setCategoryCode(parent.getCategoryCode() + code);
            baseCategory.setCategoryFullName(parent.getCategoryFullName() + CommonConstants.SPLIT_CHAR_2 + baseCategory.getCategoryName());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBaseCategory(BaseCategory baseCategory) {
        return updateById(baseCategory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteBaseCategoryByIds(String[] categoryIds) {
        List<String> idList = Arrays.asList(categoryIds);
        //判断是否有子分类
        List<BaseCategory> categoryList = getBaseCategoryByParent(idList);
        if (CollUtil.isNotEmpty(categoryList)) {
            throw new ServiceException("存在子分类不能删除!");
        }
        int batch = baseMapper.deleteBatchIds(idList);
        return batch == categoryIds.length;
    }

    /**
     * 查询父分类下的子分类
     *
     * @param idList 父分类id
     * @return 结果
     */
    private List<BaseCategory> getBaseCategoryByParent(List<String> idList) {
        LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BaseCategory::getCategoryId, idList);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<BaseCategory> selectBaseCategoryList(BaseCategoryQuery query) {
        LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(BaseCategory::getCategoryCode);
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(BaseCategory baseCategory) {
        if (CommonConstants.STATUS_DISABLE.equals(baseCategory.getCategoryStatus())) {
            LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BaseCategory::getParentId, baseCategory.getCategoryId());
            queryWrapper.eq(BaseCategory::getCategoryStatus, CommonConstants.STATUS_ENABLE);
            Long count = baseMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new ServiceException("该分类下存在启用的子分类不能禁用!");
            }
        }

        LambdaUpdateWrapper<BaseCategory> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(BaseCategory::getCategoryStatus, baseCategory.getCategoryStatus());
        updateWrapper.eq(BaseCategory::getCategoryId, baseCategory.getCategoryId());
        return this.update(updateWrapper);
    }

    @Override
    public List<BaseCategoryDto> selectBaseCategoryTree(BaseCategoryQuery query) {
        List<BaseCategory> categoryList = this.selectBaseCategoryList(query);
        return categoryList.stream()
                .filter(item -> BaseConstants.CATEGORY_ROOT_ID.equals(item.getParentId()))
                .map(item -> {
                    BaseCategoryDto dto = new BaseCategoryDto();
                    BeanUtils.copyProperties(item, dto);
                    dto.setChildren(buildChildCategory(item, categoryList));
                    return dto;
                }).collect(Collectors.toList());
    }

    @Override
    public BaseCategory getBaseCategoryByCode(String categoryCode) {
        LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseCategory::getCategoryCode,categoryCode);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 封装子分类
     *
     * @param category     父分类
     * @param categoryList 分类数据
     * @return 结果
     */
    private List<BaseCategoryDto> buildChildCategory(BaseCategory category, List<BaseCategory> categoryList) {
        return categoryList.stream()
                .filter(item ->
                        item.getParentId().equals(category.getCategoryId())
                )
                .map(item -> {
                    BaseCategoryDto dto = new BaseCategoryDto();
                    BeanUtils.copyProperties(item, dto);
                    List<BaseCategoryDto> dtoList = buildChildCategory(item, categoryList);
                    if(CollUtil.isNotEmpty(dtoList)){
                        dto.setChildren(dtoList);
                    }
                    return dto;
                }).collect(Collectors.toList());
    }

    @Override
    public String checkExcelData(BaseCategoryDto baseCategoryDto) {
        StringBuilder error = new StringBuilder();
        if (StringUtils.isEmpty(baseCategoryDto.getParentCategoryCode())) {
            error.append("父分类编码不能为空!");
        } else {
            BaseCategory category = getCategoryByCode(baseCategoryDto.getParentCategoryCode());
            if (category == null) {
                error.append("父分类[").append(baseCategoryDto.getParentCategoryCode()).append("]不存在!");
            } else {
                baseCategoryDto.setParentId(category.getCategoryId());
                baseCategoryDto.setCategoryLevel(category.getCategoryLevel() + 1);
            }
        }

        if (StringUtils.isEmpty(baseCategoryDto.getCategoryName())) {
            error.append("分类名称不能为空!");
        } else if (StringUtils.isNotEmpty(baseCategoryDto.getParentId()) && checkCategoryNameExists(baseCategoryDto.getCategoryName(), baseCategoryDto.getParentId())) {
            error.append("父分类[").append(baseCategoryDto.getParentCategoryCode()).append("]下已经存在该分类[").append(baseCategoryDto.getCategoryName()).append("]!");
        }

        String status = BizStatus.converterCode(baseCategoryDto.getCategoryStatus());
        if (StringUtils.isEmpty(status)) {
            error.append("分类状态不能为空!");
        } else {
            baseCategoryDto.setCategoryStatus(status);
        }
        return error.toString();
    }

    /**
     * 判断同一父分类下是否有相同的分类名称
     *
     * @param categoryName     分类名称
     * @param parentCategoryId 父分类id
     * @return 结果
     */
    private boolean checkCategoryNameExists(String categoryName, String parentCategoryId) {
        LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseCategory::getCategoryName, categoryName);
        queryWrapper.eq(BaseCategory::getParentId, parentCategoryId);
        return baseMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 根据编码获取产品分类
     *
     * @return 分类信息
     */
    private BaseCategory getCategoryByCode(String categoryCode) {
        LambdaQueryWrapper<BaseCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BaseCategory::getCategoryCode, categoryCode);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveExcelData(List<BaseCategoryDto> dataList) {
        if (CollUtil.isEmpty(dataList)) {
            throw new ServiceException("需要保存的分类信息为空!");
        }
        List<BaseCategory> categories = dataList.stream().map(item -> {
            BaseCategory baseCategory = new BaseCategory();
            BeanUtils.copyProperties(item, baseCategory);
            setCategoryInfo(baseCategory);
            return baseCategory;
        }).collect(Collectors.toList());
        this.saveBatch(categories);
    }
}
